package com.woniu.controller;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.woniu.utils.RedisKeyUtil;
import com.woniu.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 测试类
 */
@Slf4j
@Component
@ServerEndpoint("/websocket/{username}/{roomNum}")
//此注解相当于设置访问URL
public class WebSocket1 {

    private static RedisUtil redisUtil = SpringCtxUtils.getBean(RedisUtil.class);;

    private Session session;
    /**
     * 用来记录房间及人数 string 的数据表示房间号 set的数据表示所有人的 session 可以通过这个 来推送消息
     */
    private static Map<String, Set> roomMap = new ConcurrentHashMap(8);
    /**
     * 用来记录session_id与用户id之间的关系
     */
    public static Map<String, Integer> userIdMap = new ConcurrentHashMap(8);

//    Integer userId = BaseContext.getCurrentId();
    public static ObjectMapper objectMapper =new ObjectMapper();



    //因为 WebSocket 类中没有任何方法来初始化对象。 所以我们使用静态注入 干不起


//    private static RedisUtil redisUtil;
//    @Autowired
//    public void setRedisUtil(RedisUtil redisUtil){
//        RedisUtil.redisutil = redisUtil;
//    }




    @OnOpen
    public void open(@PathParam("roomNum") String roomId, Session session, @PathParam("username") Integer userId) throws IOException {
        //System.out.println("______________________");
        //System.out.println(userId);
        //System.out.println(roomId);
        try {
            //System.out.println(roomId);
            Set set = roomMap.get(roomId);
            //System.out.println(userId);
            userIdMap.put(session.getId(), userId);
            System.out.println("我是用来表示用户的sessionid");
            System.out.println(session.getId());
            // 如果是新的房间，则创建一个映射，如果房间已存在，则把用户放进去
            if (set == null) {
                //System.out.println("我进来了");
                set = new CopyOnWriteArraySet();
                set.add(session);
                roomMap.put(roomId, set);
                System.out.println(roomMap.get(roomId));
            } else {
                set.add(session);
            }


        } catch (Exception e) {
            e.printStackTrace();
        }

        //如果存在 历史消息 立即加载 推送给未推送消息的用户
        Set<Session> sessions = roomMap.get(roomId);

        for (Session s : sessions) {
            System.out.println("我是链接打开时的Session"+s);
            if (s.getId()==session.getId()){ //当前session 的getId 和房间里面已有的session的id 相等 才推送
                if (redisUtil.exist(RedisKeyUtil.talkRoomNum(roomId))){
                    //取出zest 的数据 (默认是从小到大的数据排序)
                    Set<String> zrange = redisUtil.zrange(RedisKeyUtil.talkRoomNum(roomId));
                    for (String messages : zrange) {
                        HashMap hashMap = objectMapper.readValue(messages, HashMap.class);
                        System.out.println(hashMap);
                        s.getBasicRemote().sendText(messages);
                    }
                }
            }
        }



    }

    //
    @OnClose
    public void onClose(@PathParam("roomNum") String roomId, Session session) {
        userIdMap.remove(session.getId());
        // 如果某个用户离开了，就移除相应的信息
        if (roomMap.containsKey(roomId)) {
            roomMap.get(roomId).remove(session);
        }
    }

    @OnMessage
    public void reveiveMessage(@PathParam("roomNum") String roomId, Session session, String message) throws IOException, IOException {
        log.info("接受到用户{}的数据:{}", session.getId(), message);

        Integer userId = userIdMap.get(session.getId());


        /**
         * message 数据格式
         * time 可以用来做时间排序
         {"message":"3333","username":"3","userName":"吴彦祖","userImg":"../../static/img/headImg/mr.png","roleName":"用户","time":1713841404318}
         */
        System.out.println("!!!!!!!!!!!!");
        System.out.println(message);
        if (message!=null||!message.equals("")){
            //存入redis 中
            //1.首先 判断 redis 中是否有这个key 没有 新增 有 累加
            if (redisUtil.exist(RedisKeyUtil.talkRoomNum(roomId))){
                //存在的情况 累加
                redisUtil.zincrby(RedisKeyUtil.talkRoomNum(roomId),message,1d);
            }else {
                //不存在的情况 新增 score 就是为了 排序的 zadd 的score 是设置初始分数
                //而 zincrby 是在上一条数据的分数 上增加 你指定的分数
                redisUtil.zadd(RedisKeyUtil.talkRoomNum(roomId),message,0);
            }
        }



        session.getBasicRemote().sendText(message);

        // 拼接一下用户信息

        Set<Session> sessions = roomMap.get(roomId);

        // 给房间内所有用户推送信息
        for (Session s : sessions) {
            System.out.println("@@@@@@@@@@@@@@");
            System.out.println(session.getId());
            System.out.println(s);
            //当前 id 和 房间的session 的id 不相等 才推送 避免重复推送
            if (s.getId()!=session.getId()){
                s.getBasicRemote().sendText(message);
            }



//            if (!s.getId().equals(session.getId())) {
//                System.out.println("我发送信息了");
//                s.getBasicRemote().sendText(message);
//            }
        }
    }


    @OnError
    public void error(Throwable error) {
//        try {
//            throw error;
//        } catch (Throwable e) {
//            log.error("未知错误");
//        }
        log.error("发生错误");
        error.printStackTrace();
    }
}
